package com.common.sdk.net.download;

import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.PriorityBlockingQueue;

import com.common.sdk.net.download.callback.CallbackObservable;
import com.common.sdk.net.download.callback.interfaces.IDownloadCallback;
import com.common.sdk.net.download.db.ControlCacheAndDb;
import com.common.sdk.net.download.dispatcher.DownloadAloneDispatcher;
import com.common.sdk.net.download.interfaces.IDownloadBuilder;
import com.common.sdk.net.download.request.model.DownloadInfo;
import com.common.sdk.net.download.util.DownloadInfoComparatorUtils;
import com.common.sdk.net.download.util.DownloadLog;
import com.common.sdk.net.connect.http.HttpStack;

/**
 * 线程控制类  单线程下载控制类
 * @author wenlonglv
 *
 */
public class DownloadQueue implements IDownloadBuilder {
    /**同时能够下载几个文件*/
    private static final int DEFAULT_NETWORK_THREAD_POOL_SIZE = 2;
    /**同时一个文件几个线程下载*/
    public static final int DEFAULT_FILE_POOL_SIZE = 8;

    private HttpStack stack;
    private DownloadAloneDispatcher[] downloadAloneDispatcher;

    private final BlockingQueue<DownloadInfo> downloadWaitQueue;

    private final Hashtable<String, DownloadInfo> absDownloadInfoTable;

    private final ExecutorService pool = Executors.newSingleThreadExecutor();

    protected DownloadQueue(HttpStack stack) {
        this(stack, DEFAULT_NETWORK_THREAD_POOL_SIZE);
    }

    protected DownloadQueue(HttpStack stack, int threadPoolSize) {
        this.stack = stack;
        this.downloadWaitQueue = new PriorityBlockingQueue<DownloadInfo>(11, new DownloadInfoComparatorUtils());
        this.downloadAloneDispatcher = new DownloadAloneDispatcher[threadPoolSize];
        this.absDownloadInfoTable = new Hashtable<String, DownloadInfo>(threadPoolSize);
    }

    @Override
    public void initialization() {
        // stopALl(); 用不用实现在考虑 TODO
        DownloadLog.error("DownloadQueue initialization ");
        runDownload(new Runnable() {
            @Override
            public void run() {
                ControlCacheAndDb.initialize(downloadWaitQueue, absDownloadInfoTable);
            }
        });
        for (int i = 0; i < downloadAloneDispatcher.length; i++) {
            downloadAloneDispatcher[i] = new DownloadAloneDispatcher(stack, downloadWaitQueue, absDownloadInfoTable);
            downloadAloneDispatcher[i].start();
        }
    }

    @Override
    public void registerCallback(IDownloadCallback cb) {
        DownloadLog.error("DownloadQueue registerCallback ");
        CallbackObservable.getIntence().registerObserver(cb);
    }

    @Override
    public void unregisterCallback(IDownloadCallback cb) {
        DownloadLog.error("DownloadQueue unregisterCallback ");
        CallbackObservable.getIntence().removeObserver(cb);
    }

    private void runDownload(Runnable run) {
        pool.submit(run);
    }

    @Override
    public void deleteAndAddDownloadItem(final DownloadInfo downloadInfo) {
        runDownload(new Runnable() {

            @Override
            public void run() {
                DownloadLog.error("DownloadQueue addDownloadItem ");
                ControlCacheAndDb.deleteAndAddDownloadItem(downloadInfo, downloadWaitQueue, absDownloadInfoTable);
            }
        });
    }

    @Override
    public void addDownloadItem(final DownloadInfo downloadInfo) {
        runDownload(new Runnable() {

            @Override
            public void run() {
                DownloadLog.error("DownloadQueue addDownloadItem ");
                ControlCacheAndDb.addDownloadItem(downloadInfo, downloadWaitQueue, absDownloadInfoTable);
            }
        });
    }

    @Deprecated
    @Override
    public void addDownloadItem(final DownloadInfo downloadInfo, final boolean isSdEnableDownload) {
        runDownload(new Runnable() {

            @Override
            public void run() {
                DownloadLog.error("DownloadQueue addDownloadItem ");
                ControlCacheAndDb.addDownloadItem(downloadInfo, isSdEnableDownload, downloadWaitQueue,
                        absDownloadInfoTable);
            }
        });
    }

    @Override
    public void addDownloadList(final List<? extends DownloadInfo> downloadInfoAddLists) {
        runDownload(new Runnable() {
            @Override
            public void run() {
                DownloadLog.error("DownloadQueue addDownloadList ");
                ControlCacheAndDb.addDownloadList(downloadInfoAddLists, downloadWaitQueue, absDownloadInfoTable);
            }
        });
    }

    @Override
    public void pauseDownloadItem(final DownloadInfo downloadInfo) {
        runDownload(new Runnable() {
            @Override
            public void run() {
                DownloadLog.error("DownloadQueue pauseDownloadItem ");
                ControlCacheAndDb.pauseDownloadItem(downloadInfo, downloadWaitQueue);
            }
        });
    }

    @Override
    public void pauseDownloadList(final List<? extends DownloadInfo> downloadInfoPauseLists) {
        runDownload(new Runnable() {
            @Override
            public void run() {
                DownloadLog.error("DownloadQueue pauseDownloadList ");
                for (DownloadInfo downloadInfoPauseList : downloadInfoPauseLists) {
                    ControlCacheAndDb.pauseDownloadItem(downloadInfoPauseList, downloadWaitQueue);
                }
            }
        });
    }

    @Override
    public void startDownloadItem(final DownloadInfo downloadInfo) {
        runDownload(new Runnable() {
            @Override
            public void run() {
                DownloadLog.error("DownloadQueue startDownloadItem ");
                ControlCacheAndDb.startDownloadItem(downloadInfo, downloadWaitQueue, absDownloadInfoTable);
            }
        });
    }

    @Override
    public void startDownloadItem(final DownloadInfo downloadInfo, final boolean isSdEnableDownload) {
        runDownload(new Runnable() {
            @Override
            public void run() {
                DownloadLog.error("DownloadQueue startDownloadItem ");
                ControlCacheAndDb.startDownloadItem(downloadInfo, isSdEnableDownload, downloadWaitQueue,
                        absDownloadInfoTable);
            }
        });
    }

    @Override
    public void startDownloadList(final List<? extends DownloadInfo> downloadInfoStartLists) {
        runDownload(new Runnable() {
            @Override
            public void run() {
                DownloadLog.error("DownloadQueue startDownloadList ");
                for (DownloadInfo downloadInfoStartList : downloadInfoStartLists) {
                    ControlCacheAndDb.startDownloadItem(downloadInfoStartList, downloadWaitQueue, absDownloadInfoTable);
                }
            }
        });
    }

    @Override
    public void stopDownloadingItem(final DownloadInfo downloadInfo) {
        runDownload(new Runnable() {
            @Override
            public void run() {
                DownloadLog.error("DownloadQueue stopDownloadingItem ");
                ControlCacheAndDb.stopDownloadingItem(downloadInfo);
            }
        });
    }

    @Override
    public void stopDownloadList(final List<? extends DownloadInfo> downloadInfoStopLists) {
        runDownload(new Runnable() {
            @Override
            public void run() {
                DownloadLog.error("DownloadQueue stopDownloadList ");
                for (DownloadInfo downloadInfoStopList : downloadInfoStopLists) {
                    ControlCacheAndDb.stopDownloadingItem(downloadInfoStopList);
                }
            }
        });
    }

    @Override
    public void deleteDownloadItem(final DownloadInfo downloadInfo) {
        runDownload(new Runnable() {
            @Override
            public void run() {
                DownloadLog.error("DownloadQueue deleteDownloadItem ");
                ControlCacheAndDb.deleteDownloadItem(downloadInfo, absDownloadInfoTable);
            }
        });
    }

    @Override
    public void deleteDownloadList(final List<? extends DownloadInfo> downloadInfoDeleteLists) {
        runDownload(new Runnable() {
            @Override
            public void run() {
                DownloadLog.error("DownloadQueue deleteDownloadList ");
                ControlCacheAndDb.deleteDownloadList(downloadInfoDeleteLists, absDownloadInfoTable);
            }
        });
    }

    @Override
    public List<DownloadInfo> getDownloadingList() {
        DownloadLog.error("DownloadQueue getDownloadingList ");
        return ControlCacheAndDb.getDownloadingList();
    }

    @Override
    public List<DownloadInfo> getDownloadedList() {
        DownloadLog.error("DownloadQueue getDownloadedList ");
        return ControlCacheAndDb.getDownloadedList();
    }

    @Override
    public HashMap<String, DownloadInfo> getDownloadGeneral() {
        DownloadLog.error("DownloadQueue getDownloadedList ");
        return ControlCacheAndDb.getDownloadGeneral();
    }

    @Override
    public void restartAllStopTasks() {
        runDownload(new Runnable() {
            @Override
            public void run() {
                DownloadLog.error("DownloadQueue restartAllStopTasks ");
                ControlCacheAndDb.restartAllStopTasks(downloadWaitQueue, absDownloadInfoTable);
            }
        });
    }

    @Override
    public void restartAllSDStopTasks(final boolean isSdEnableDownload) {
        // TODO Auto-generated method stub
        runDownload(new Runnable() {
            @Override
            public void run() {
                DownloadLog.error("DownloadQueue restartAllStopTasks ");
                ControlCacheAndDb.restartAllStopTasks(isSdEnableDownload, downloadWaitQueue, absDownloadInfoTable);
            }
        });
    }

    @Override
    public void restartAllPauseTasks() {
        runDownload(new Runnable() {

            @Override
            public void run() {
                DownloadLog.error("DownloadQueue restartAllPauseTasks ");
                ControlCacheAndDb.restartAllPauseTasks(downloadWaitQueue, absDownloadInfoTable);
            }
        });
    }

    @Override
    public void restartAllTasks() {
        // TODO Auto-generated method stub
        runDownload(new Runnable() {
            @Override
            public void run() {
                DownloadLog.error("DownloadQueue restartAllTasks ");
                ControlCacheAndDb.restartAllTasks(downloadWaitQueue);
            }
        });
    }

    @Override
    public void pauseAllDownloadingTasks() {
        runDownload(new Runnable() {
            @Override
            public void run() {
                DownloadLog.error("DownloadQueue pauseAllDownloadingTasks ");
                ControlCacheAndDb.pauseAllDownloadingTasks(downloadWaitQueue);
            }
        });
    }

    @Override
    public void stopAllDownloadingTasks() {
        runDownload(new Runnable() {
            @Override
            public void run() {
                DownloadLog.error("DownloadQueue stopAllDownloadingTasks ");
                ControlCacheAndDb.stopAllDownloadingTasks(downloadWaitQueue);
            }
        });
    }

}
